package eventServer;

import java.net.*;
import java.io.IOException;

import eventServer.NodeEventServant;
import eventServer.NodeEventServer;
import eventServer.NodeEventService;
import event.Event;
import node.Node;
import node.NodeDescriptor;

/**
 * This class represents the server who will wait to receive the external event that will be managed by servant and implements 
 * the Runnable interface and NodeEventService interface
 * @see java.lang.Runnable
 * @see eventServer.NodeEventService
 * @author 
 *
 */
public class NodeEventServer implements NodeEventService, Runnable{
	protected Node 	theNode;
	protected int 	port;
	protected int 	datagramBufferSize;
	protected String ip;
	
	/**
	 * Builder
	 * @param aNode
	 */
	public NodeEventServer(Node aNode)
	{
		super();
		theNode = aNode;
				
		port 	= NodeDescriptor.getInstance().getEES().getPort();
		datagramBufferSize = NodeDescriptor.getInstance().getESize();
		ip 		= NodeDescriptor.getInstance().getIp();
	}
	
	/**
	 * Implementation of the run method of the Runnable interface.
	 * Prepare a DatagramPacket to receive the request from a node and create the servant thread to suit the received request
	 * @see java.net
	 * @see eventServer.NodeEventServant
	 * @exception SocketException
	 * @exception IOException
	 */
	@Override
	public void run() {
		// TODO Auto-generated method stub

		// Get the current configurations
		try {
			// Initializing the UDP Socket and wait for a new UDP.
			DatagramSocket theSocketComm = new DatagramSocket(port);
			System.out.println(" >> NodeEventServer: Server's Up @ " + this.ip + ":" + this.port);
			
			while(true)
			{
				// Initializing an UDP Package for receiving Requests
				byte[] buffer = new byte[datagramBufferSize];
				DatagramPacket receivedPacket = new DatagramPacket(buffer, this.datagramBufferSize);
				
				theSocketComm.receive(receivedPacket);
				
				System.out.println("\n-----------------------------\n\n >> NodeEventServer: Received new UDP Packet From " + 
						receivedPacket.getAddress() + 
						":" + 
						receivedPacket.getPort() +
						". Detaching new Servant");
				
				// Spawn a Servant Thread
				NodeEventServant servant = new NodeEventServant(this, receivedPacket);
				new Thread(servant, "NodeEventServant").start();
			}
		
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			System.out.println(" >> NodeEventServer: Cannot create Datagram Socket.\nDetail: " + e.getMessage());		
		} catch (IOException e) {
			System.out.println(" >> NodeEventServer: Cannot receive Remote UDP\nDetail: " + e.getMessage());
		}
	}

	/**
	 * 
	 */
	@Override
	public void submitEvent(Event e) {
		// TODO Auto-generated method stub
		theNode.submitEvent(e);
		
	}
	
	/**
	 * 
	 */
	@Override
	public Event dequeueEvent() {
		// TODO Auto-generated method stub
		//return theNode.dequeueEvent();
		return null;
	}
}